﻿using System;
using System.Linq;

using zijian666.Abstractions;
using zijian666.Convertor.Base;
using zijian666.ConvertExtensions;

namespace zijian666.Core;

/// <summary>
/// 转换程序编译器
/// </summary>
/// <param name="_factories">转换器工厂集合</param>
/// <exception cref="ArgumentNullException"></exception>
public class ConvertorBuilder(IConvertorFactory[] _factories)
{
    /// <summary>
    /// 编译转换器
    /// </summary>
    public IConvertor<T> Build<T>()
    {
        var outputType = typeof(T);
        if (outputType.IsGenericTypeDefinition)
        {
            return new ErrorConvertor<T>(outputType.GetFriendlyName(), nameof(ResourceStrings.CLASS_IS_GENERIC_TYPE_DEFINITION));
        }
        if (outputType.IsAbstract && outputType.IsSealed)
        {
            return new ErrorConvertor<T>(nameof(ResourceStrings.CLASS_IS_STATIC));
        }
        if (_factories is null || _factories.Length == 0)
        {
            return new ErrorConvertor<T>(nameof(ResourceStrings.CONVERTOR_NOT_FOUND));
        }
        var convs = _factories
            .Select(x => x.Create<T>())
            .Where(x => x.MacthedType != MacthedType.NotMatched)
            .OrderBy(x => x.MacthedType)                    // 根据匹配类型排序
            .ThenByDescending(x => x.Convertor.Priority)    // 然后根据转换器优先级倒序
            .Select(x => x.Convertor)
            .ToList();

        // 移除存在父子类关系的转换器 
        convs.RemoveAll(x => convs.Any(n => x != n && x.GetType().IsAssignableFrom(n.GetType())));

        return convs.Count switch
        {
            0 => new ErrorConvertor<T>(nameof(ResourceStrings.CONVERTOR_NOT_FOUND)),
            1 => new AspectConvertor<T>(convs[0]),
            _ => new AggregateConvertor<T>(convs.Select(x => new AspectConvertor<T>(x))),
        };
    }
}
